package com.bestcem.xm.label.grpc.service;

import com.bestcem.xm.common.core.constant.RegTypes;
import com.bestcem.xm.common.core.domain.web.RpcStatusResult;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.uitls.GRpcUtil;
import com.bestcem.xm.label.grpc.service.param.labelgroup.CreateLabelGroupParam;
import com.bestcem.xm.label.grpc.service.param.labelgroup.UpdateLabelGroupNameParam;
import com.bestcem.xm.label.grpc.v1.common.CreateResponse;
import com.bestcem.xm.label.grpc.v1.common.UpdateResponse;
import com.bestcem.xm.label.grpc.v1.services.*;
import com.bestcem.xm.label.service.LabelGroupService;
import com.bestcem.xm.label.service.dto.LabelGroupDTO;
import com.bestcem.xm.label.service.dto.label.LabelDTO;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.server.service.GrpcService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.validation.ConstraintViolation;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


/**
 * @author dc.wang <dc.wang@idiaoyan.com>
 * @version V1.0
 * @description 提供标签组相关rpc服务
 * @date 2021/5/18
 */
@Slf4j
@GrpcService
public class LabelGroupGrpcService extends LabelGroupServiceGrpc.LabelGroupServiceImplBase {

    @Autowired
    private LabelGroupService labelGroupService;

    /**
     * 查询企业标签组
     * @param request
     * @param responseObserver
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date: 2021/6/25
     */
    @Override
    public void listLabelGroup(
            ListLabelGroupRequest request, StreamObserver<ListLabelGroupResponse> responseObserver) {
        ListLabelGroupResponse.Builder builder = ListLabelGroupResponse.newBuilder();
        // 参数校验
        if (!StringUtils.hasText(request.getOrgId())) {
            builder.setStatus(RpcStatusResult.error("企业ID不存在！"));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }
        ServiceResult<List<LabelGroupDTO>> result = labelGroupService.listLabelGroup(request.getOrgId());
        if (result.isSuccess()) {
            builder.setStatus(RpcStatusResult.success());
            List<LabelGroup> labelGroups = result.getData().stream().map(this::convertToLabelGroup).collect(Collectors.toList());
            builder.addAllGroups(labelGroups);
        } else {
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
        }
        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    /**
     * LabelGroupDTO 转 LabelGroup
     * @param labelGroupDto
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/6/25
     */
    private LabelGroup convertToLabelGroup(LabelGroupDTO labelGroupDto) {

        LabelGroup.Builder builder = LabelGroup.newBuilder();
        builder.setId(labelGroupDto.getId());
        builder.setName(labelGroupDto.getName());

        return builder.build();
    }

    /**
     * 创建标签组
     * @param request
     * @param responseObserver
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/6/25
     */
    @Override
    public void createLabelGroup(
            CreateLabelGroupRequest request, StreamObserver<CreateResponse> responseObserver) {
        CreateResponse.Builder builder = CreateResponse.newBuilder();

        CreateLabelGroupParam createlabelGroupParam = new CreateLabelGroupParam();
        LabelGroup labelGroup = request.getGroup();
        createlabelGroupParam.setName(labelGroup.getName());
        createlabelGroupParam.setOrgId(labelGroup.getOrgId());
        createlabelGroupParam.setSerial(labelGroup.getSerial());
        createlabelGroupParam.setAttribute(labelGroup.getMemberTypeValue());

        // 参数校验
        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(createlabelGroupParam);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        ServiceResult<LabelGroupDTO> result =
                labelGroupService.createLabelGroup(createlabelGroupParam);

        if (result.isSuccess()) {
            builder.setStatus(RpcStatusResult.success()).setId(result.getData().getId());
        } else {
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
        }

        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    /**
     * 更新标签组名称
     * @param request
     * @param responseObserver
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/6/25
     */
    @Override
    public void updateLabelGroup(
            UpdateLabelGroupRequest request, StreamObserver<UpdateResponse> responseObserver) {
        UpdateResponse.Builder builder = UpdateResponse.newBuilder();

        // 参数校验
        LabelGroup labelGroup = request.getGroup();

        UpdateLabelGroupNameParam updateLabelGroupNameParam = new UpdateLabelGroupNameParam();
        updateLabelGroupNameParam.setOrgId(labelGroup.getOrgId());
        updateLabelGroupNameParam.setLabelGroupId(labelGroup.getId());
        updateLabelGroupNameParam.setName(labelGroup.getName());

        Set<ConstraintViolation<Object>> violations = GRpcUtil.validateParam(updateLabelGroupNameParam);
        if (!CollectionUtils.isEmpty(violations)) {
            ConstraintViolation<Object> violation = violations.iterator().next();
            builder.setStatus(RpcStatusResult.error(violation.getMessage()));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        ServiceResult<String> result = labelGroupService.updateLabelGroup(updateLabelGroupNameParam);

        if (result.isSuccess()) {
            builder.setStatus(RpcStatusResult.success()).setId(result.getData());
        } else {
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
        }

        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

    /**
     * 通过标签组ID删除标签组、标签、标签值、
     * @param request
     * @param responseObserver
     * @author dc.wang <dc.wang@idiaoyan.com>
     * @date 2021/6/25
     */
    @Override
    public void deleteLabelGroup(DeleteLabelGroupRequest request, StreamObserver<DeleteLabelGroupResponse> responseObserver) {
        DeleteLabelGroupResponse.Builder builder = DeleteLabelGroupResponse.newBuilder();

        // 校验参数
        if (!Pattern.matches(RegTypes.OBJECT_ID, request.getId())) {
            builder.setStatus(RpcStatusResult.error(String.format("标签组ID：%s 格式异常！", request.getId())));
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
            return;
        }

        ServiceResult<LabelGroupDTO> result =
                labelGroupService.deleteLabelGroup(request.getId());

        if (result.isSuccess()) {
            builder.setStatus(RpcStatusResult.success());
            List<String> labelIds = result.getData().getLabelDTOS().stream().map(LabelDTO::getId).collect(Collectors.toList());
            builder.addAllLabelIds(labelIds);
        } else {
            builder.setStatus(RpcStatusResult.error(result.getMsg()));
        }

        responseObserver.onNext(builder.build());
        responseObserver.onCompleted();
    }

}
